OPC Studio User's Guide and Reference
Pull Data Consumption Model
Concepts > OPC Wizard Concepts > OPC Wizard Operation Model > Data Provision And Consumption Models > Pull Data Consumption Model
In This Topic

General

In the pull data consumption model, the OPC Write requests simply store the written data in the data variable object. You then write an independently running code that retrieves (pulls) the data from the data variable(s), and sends the data to the underlying system.

OPC Wizard stores the data written to the data variable in its WriteAttributeData Property. Your code retrieves the written data by getting the value of this property. When and how it is done is completely up to you, and depends highly on the specifics of the OPC server you are developing. In many cases, the retrieval will be based on some kind of periodic timer. In other scenarios, it may be triggered by the underlying system or connected device.

The pull data consumption model is inherently asynchronous, i.e. the actual data writing to the underlying system happens independently of the actual OPC Write call. This has several consequences, such as that the true outcome of the write operation cannot be returned to the OPC client, and also that the actual writing occurs at possibly later time, after the OPC Write request is fulfilled. The pull data consumption model can therefore be only used in applications where this behavior does not pose a problem.

Conversely, the advantage of the pull data consumption model is that OPC Writes are fulfilled very quickly, as the code that sends the data to the underlying system cannot "block" the OPC server.

The following picture illustrates how the pull data consumption model works.

 

For performance reasons, consider setting the PropagateWrite Property of the data variable to false. Since there is no handling of the Write Event or overriding of the OnWrite Method in the pull data consumption model, Write request propagation is unnecessary.

.NET

// This example shows how to retrieve the attribute data in the pull data consumption model. In this model, the data that
// OPC clients write to the server is pulled and processed by your code when needed.
// You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
//
// Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
// OPC client, server and subscriber examples in C# on GitHub: https://github.com/OPCLabs/Examples-OPCStudio-CSharp .
// Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
// a commercial license in order to use Online Forums, and we reply to every post.

using System;
using System.Timers;
using OpcLabs.EasyOpc.UA;
using OpcLabs.EasyOpc.UA.NodeSpace;

namespace UAServerDocExamples._UADataVariable
{
    class WriteAttributeData
    {
        public static void Main1()
        {
            // Instantiate the server object.
            // By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            var server = new EasyUAServer();

            // Create a read-write data variable with an initial value.
            var dataVariable = UADataVariable.CreateIn(server.Objects, "WriteToThisVariable").ReadWriteValue(0);

            // Create a timer for pulling the data from OPC writes. In a real server the activity may also come from other
            // sources.
            var timer = new Timer
            {
                Interval = 1000,
                AutoReset = true,
            };

            // Periodically display the value of the data variable on the console.
            timer.Elapsed += (sender, args) => Console.Write($"  {dataVariable.WriteAttributeData.Value}");
            timer.Start();
            Console.WriteLine("Values of the example data variable are displayed on the console periodically.");

            // Start the server.
            Console.WriteLine("The server is starting...");
            server.Start();

            Console.WriteLine("The server is started.");
            Console.WriteLine();

            // Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...");
            Console.ReadLine();

            // Stop the server.
            Console.WriteLine("The server is stopping...");
            server.Stop();

            // Stop the timer.
            timer.Stop();

            Console.WriteLine("The server is stopped.");
        }
    }
}
' This example shows how to retrieve the attribute data in the pull data consumption model. In this model, the data that
' OPC clients write to the server is pulled and processed by your code when needed.
' You can use any OPC UA client, including our Connectivity Explorer and OpcCmd utility, to connect to the server. 
'
' Find all latest examples here: https://opclabs.doc-that.com/files/onlinedocs/OPCLabs-OpcStudio/Latest/examples.html .
' OPC client and subscriber examples in VB.NET on GitHub: https://github.com/OPCLabs/Examples-QuickOPC-VBNET .
' Missing some example? Ask us for it on our Online Forums, https://www.opclabs.com/forum/index ! You do not have to own
' a commercial license in order to use Online Forums, and we reply to every post.

Imports System
Imports System.Timers
Imports OpcLabs.EasyOpc.UA
Imports OpcLabs.EasyOpc.UA.NodeSpace

Namespace _UADataVariable
    Partial Friend Class WriteAttributeData
        Shared Sub Main1()
            ' Instantiate the server object.
            ' By default, the server will run on endpoint URL "opc.tcp://localhost:48040/".
            Dim server = New EasyUAServer()

            ' Create a read-write data variable with an initial value.
            Dim dataVariable = UADataVariable.CreateIn(server.Objects, "WriteToThisVariable").ReadWriteValue(0)

            ' Create a timer for pulling the data from OPC writes. In a real server the activity may also come from other
            ' sources.
            Dim timer = New Timer With
            {
                .Interval = 1000,
                .AutoReset = True
            }

            ' Periodically display the value of the data variable on the console.
            AddHandler timer.Elapsed, Sub(sender, args) Console.Write($"  {dataVariable.WriteAttributeData.Value}")
            timer.Start()
            Console.WriteLine("Values of the example data variable are displayed on the console periodically.")

            ' Start the server.
            Console.WriteLine("The server is starting...")
            server.Start()

            Console.WriteLine("The server is started.")
            Console.WriteLine()

            ' Let the user decide when to stop.
            Console.WriteLine("Press Enter to stop the server...")
            Console.ReadLine()

            ' Stop the server.
            Console.WriteLine("The server is stopping...")
            server.Stop()

            ' Stop the timer.
            timer.Stop()

            Console.WriteLine("The server is stopped.")
        End Sub
    End Class
End Namespace

Initial Data

When using the pull data consumption model, in general, you are responsible for providing the initial contents of the WriteAttributeData Property. Make sure you have a reasonable contents even before your code first gets a chance to pull the data variable and process it. WIthout further configuration, the WriteAttributeData Property contains empty data - meaning that the status code is "Good", but there is no timestamp, and the value itself is null. This may not be what you want - especially with non-nullable types where null is not even a valid value for the data type of your variable. You always need to specify initial data that make sense for your server or application.

Many extension methods for Data Variable Configuration already initialize the WriteAttributeData Property at least to the default value for the given data type. This assures that the initial value is valid for that data type, but it still may not be the "right" value for your server. Some data variable configuration extension methods (such as the ReadWriteValue Method) allow you (and force you to) specify the initial data (or just the value) directly as an argument in the method call.

See Also

Examples - Server OPC Unified Architecture

Reference